﻿#pragma warning disable CS8604 // Possible null reference argument.

using Crux.Core.SQL.Formatter.Core;

namespace Crux.Core.SQL.Formatter.Language;
/// <summary>
/// 
/// </summary>
public class PlSqlFormatter : AbstractFormatter
{
    private readonly static List<string> ReservedWords = new List<string>{
        "A",
        "ACCESSIBLE",
        "AGENT",
        "AGGREGATE",
        "ALL",
        "ALTER",
        "ANY",
        "ARRAY",
        "AS",
        "ASC",
        "AT",
        "ATTRIBUTE",
        "AUTHID",
        "AVG",
        "BETWEEN",
        "BFILE_BASE",
        "BINARY_INTEGER",
        "BINARY",
        "BLOB_BASE",
        "BLOCK",
        "BODY",
        "BOOLEAN",
        "BOTH",
        "BOUND",
        "BREADTH",
        "BULK",
        "BY",
        "BYTE",
        "C",
        "CALL",
        "CALLING",
        "CASCADE",
        "CASE",
        "CHAR_BASE",
        "CHAR",
        "CHARACTER",
        "CHARSET",
        "CHARSETFORM",
        "CHARSETID",
        "CHECK",
        "CLOB_BASE",
        "CLONE",
        "CLOSE",
        "CLUSTER",
        "CLUSTERS",
        "COALESCE",
        "COLAUTH",
        "COLLECT",
        "COLUMNS",
        "COMMENT",
        "COMMIT",
        "COMMITTED",
        "COMPILED",
        "COMPRESS",
        "CONNECT",
        "CONSTANT",
        "CONSTRUCTOR",
        "CONTEXT",
        "CONTINUE",
        "CONVERT",
        "COUNT",
        "CRASH",
        "CREATE",
        "CREDENTIAL",
        "CURRENT",
        "CURRVAL",
        "CURSOR",
        "CUSTOMDATUM",
        "DANGLING",
        "DATA",
        "DATE_BASE",
        "DATE",
        "DAY",
        "DECIMAL",
        "DEFAULT",
        "DEFINE",
        "DELETE",
        "DEPTH",
        "DESC",
        "DETERMINISTIC",
        "DIRECTORY",
        "DISTINCT",
        "DO",
        "DOUBLE",
        "DROP",
        "DURATION",
        "ELEMENT",
        "ELSIF",
        "EMPTY",
        "END",
        "ESCAPE",
        "EXCEPTIONS",
        "EXCLUSIVE",
        "EXECUTE",
        "EXISTS",
        "EXIT",
        "EXTENDS",
        "EXTERNAL",
        "EXTRACT",
        "FALSE",
        "FETCH",
        "FINAL",
        "FIRST",
        "FIXED",
        "FLOAT",
        "FOR",
        "FORALL",
        "FORCE",
        "FROM",
        "FUNCTION",
        "GENERAL",
        "GOTO",
        "GRANT",
        "GROUP",
        "HASH",
        "HEAP",
        "HIDDEN",
        "HOUR",
        "IDENTIFIED",
        "IF",
        "IMMEDIATE",
        "IN",
        "INCLUDING",
        "INDEX",
        "INDEXES",
        "INDICATOR",
        "INDICES",
        "INFINITE",
        "INSTANTIABLE",
        "INT",
        "INTEGER",
        "INTERFACE",
        "INTERVAL",
        "INTO",
        "INVALIDATE",
        "IS",
        "ISOLATION",
        "JAVA",
        "LANGUAGE",
        "LARGE",
        "LEADING",
        "LENGTH",
        "LEVEL",
        "LIBRARY",
        "LIKE",
        "LIKE2",
        "LIKE4",
        "LIKEC",
        "LIMITED",
        "LOCAL",
        "LOCK",
        "LONG",
        "MAP",
        "MAX",
        "MAXLEN",
        "MEMBER",
        "MERGE",
        "MIN",
        "MINUTE",
        "MLSLABEL",
        "MOD",
        "MODE",
        "MONTH",
        "MULTISET",
        "NAME",
        "NAN",
        "NATIONAL",
        "NATIVE",
        "NATURAL",
        "NATURALN",
        "NCHAR",
        "NEW",
        "NEXTVAL",
        "NOCOMPRESS",
        "NOCOPY",
        "NOT",
        "NOWAIT",
        "NULL",
        "NULLIF",
        "NUMBER_BASE",
        "NUMBER",
        "OBJECT",
        "OCICOLL",
        "OCIDATE",
        "OCIDATETIME",
        "OCIDURATION",
        "OCIINTERVAL",
        "OCILOBLOCATOR",
        "OCINUMBER",
        "OCIRAW",
        "OCIREF",
        "OCIREFCURSOR",
        "OCIROWID",
        "OCISTRING",
        "OCITYPE",
        "OF",
        "OLD",
        "ON",
        "ONLY",
        "OPAQUE",
        "OPEN",
        "OPERATOR",
        "OPTION",
        "ORACLE",
        "ORADATA",
        "ORDER",
        "ORGANIZATION",
        "ORLANY",
        "ORLVARY",
        "OTHERS",
        "OUT",
        "OVERLAPS",
        "OVERRIDING",
        "PACKAGE",
        "PARALLEL_ENABLE",
        "PARAMETER",
        "PARAMETERS",
        "PARENT",
        "PARTITION",
        "PASCAL",
        "PCTFREE",
        "PIPE",
        "PIPELINED",
        "PLS_INTEGER",
        "PLUGGABLE",
        "POSITIVE",
        "POSITIVEN",
        "PRAGMA",
        "PRECISION",
        "PRIOR",
        "PRIVATE",
        "PROCEDURE",
        "public",
        "RAISE",
        "RANGE",
        "RAW",
        "READ",
        "REAL",
        "RECORD",
        "REF",
        "REFERENCE",
        "RELEASE",
        "RELIES_ON",
        "REM",
        "REMAINDER",
        "RENAME",
        "RESOURCE",
        "RESULT_CACHE",
        "RESULT",
        "RETURN",
        "RETURNING",
        "REVERSE",
        "REVOKE",
        "ROLLBACK",
        "ROW",
        "ROWID",
        "ROWNUM",
        "ROWTYPE",
        "SAMPLE",
        "SAVE",
        "SAVEPOINT",
        "SB1",
        "SB2",
        "SB4",
        "SEARCH",
        "SECOND",
        "SEGMENT",
        "SELF",
        "SEPARATE",
        "SEQUENCE",
        "SERIALIZABLE",
        "SHARE",
        "SHORT",
        "SIZE_T",
        "SIZE",
        "SMALLINT",
        "SOME",
        "SPACE",
        "SPARSE",
        "SQL",
        "SQLCODE",
        "SQLDATA",
        "SQLERRM",
        "SQLNAME",
        "SQLSTATE",
        "STANDARD",
        "START",
        "",
        "STATIC STDDEV",
        "STORED",
        "STRING",
        "STRUCT",
        "STYLE",
        "SUBMULTISET",
        "SUBPARTITION",
        "SUBSTITUTABLE",
        "SUBTYPE",
        "SUCCESSFUL",
        "SUM",
        "SYNONYM",
        "SYSDATE",
        "TABAUTH",
        "TABLE",
        "TDO",
        "THE",
        "THEN",
        "TIME",
        "TIMESTAMP",
        "TIMEZONE_ABBR",
        "TIMEZONE_HOUR",
        "TIMEZONE_MINUTE",
        "TIMEZONE_REGION",
        "TO",
        "TRAILING",
        "TRANSACTION",
        "TRANSACTIONAL",
        "TRIGGER",
        "TRUE",
        "TRUSTED",
        "TYPE",
        "UB1",
        "UB2",
        "UB4",
        "UID",
        "UNDER",
        "UNIQUE",
        "UNPLUG",
        "UNSIGNED",
        "UNTRUSTED",
        "USE",
        "USER",
        "USING",
        "VALIDATE",
        "VALIST",
        "VALUE",
        "VARCHAR",
        "VARCHAR2",
        "VARIABLE",
        "VARIANCE",
        "VARRAY",
        "VARYING",
        "VIEW",
        "VIEWS",
        "VOID",
        "WHENEVER",
        "WHILE",
        "WITH",
        "WORK",
        "WRAPPED",
        "WRITE",
        "YEAR",
        "ZONE"};

    private readonly static List<string> ReservedTopLevelWords = new List<string>{
        "ADD",
        "ALTER COLUMN",
        "ALTER TABLE",
        "BEGIN",
        "CONNECT BY",
        "DECLARE",
        "DELETE FROM",
        "DELETE",
        "END",
        "EXCEPT",
        "EXCEPTION",
        "FETCH FIRST",
        "FROM",
        "GROUP BY",
        "HAVING",
        "INSERT INTO",
        "INSERT",
        "LIMIT",
        "LOOP",
        "MODIFY",
        "ORDER BY",
        "SELECT",
        "SET CURRENT SCHEMA",
        "SET SCHEMA",
        "SET",
        "START WITH",
        "UPDATE",
        "VALUES",
        "WHERE"
    };

    private readonly static List<string> ReservedTopLevelWordsNoIndent = new List<string> { "INTERSECT", "INTERSECT ALL", "MINUS", "UNION", "UNION ALL" };

    private readonly static List<string> ReservedNewlineWords = new List<string>{
        "AND",
        "CROSS APPLY",
        "ELSE",
        "END",
        "OR",
        "OUTER APPLY",
        "WHEN",
        "XOR",
        "JOIN",
        "INNER JOIN",
        "LEFT JOIN",
        "LEFT OUTER JOIN",
        "RIGHT JOIN",
        "RIGHT OUTER JOIN",
        "FULL JOIN",
        "FULL OUTER JOIN",
        "CROSS JOIN",
        "NATURAL JOIN"
    };
    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public override DialectConfig DoDialectConfig()
    {
        return DialectConfig.Builder()
            .ReservedWords(ReservedWords)
            .ReservedTopLevelWords(ReservedTopLevelWords)
            .ReservedTopLevelWordsNoIndent(ReservedTopLevelWordsNoIndent)
            .ReservedNewlineWords(ReservedNewlineWords)
            .StringTypes(
                new List<string>{
                        StringLiteral.DoubleQuote,
                        StringLiteral.NSingleQuote,
                        StringLiteral.QSingleQuote,
                        StringLiteral.SingleQuote,
                        StringLiteral.BackQuote})
            .OpenParens(new List<string> { "(", "CASE" })
            .CloseParens(new List<string> { ")", "END" })
            .IndexedPlaceholderTypes(new List<string> { "?" })
            .NamedPlaceholderTypes(new List<string> { ":" })
            .LineCommentTypes(new List<string> { "--" })
            .SpecialWordChars(new List<string> { "_", "$", "#", ".", "@" })
            .Operators(new List<string> { "||", "**", "!=", ":=" })
            .Build();
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="token"></param>
    /// <returns></returns>
    protected override Token TokenOverride(Token token)
    {
        if (!Token.IsSet(token) || !Token.IsBy(previousReservedToken))
        {
            return token;
        }

        return new Token(TokenTypes.RESERVED, token.value);
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="cfg"></param>
    /// <returns></returns>

    public PlSqlFormatter(FormatConfig cfg) : base(cfg)
    {
    }
}
#pragma warning restore CS8604 // Possible null reference argument.